
;--- implements sndPlaySoundA()

	.386
if ?FLAT
	.MODEL FLAT, stdcall
else
	.MODEL SMALL, stdcall
endif
	option casemap:none
	option proc:private

	include winbase.inc
	include mmsystem.inc
	include macros.inc

?BLKSIZE    equ 10000h

RIFFHDR struct
chkId   dd ?
chkSiz  dd ?
format  dd ?
RIFFHDR ends

RIFFCHKHDR struct
subchkId    dd ?
subchkSiz   dd ?
RIFFCHKHDR ends

WAVEFMT struct
    RIFFCHKHDR <>
wFormatTag      dw ?
nChannels       dw ?
nSamplesPerSec  dd ?
nAvgBytesPerSec dd ?
nBlockAlign     dw ?
wBitsPerSample  dw ?
WAVEFMT ends

	.DATA

hThread		dd 0        
dwFlags		dd 0
g_bCancel	db 0

	.CODE

LoadFile proc uses ebx esi pszFileName:ptr

local	dwRead:dword
local	dwSize:dword

		Invoke CreateFile, pszFileName, GENERIC_READ, FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
		cmp eax,-1
		jz error
		mov ebx,eax
		invoke GetFileSize, eax, NULL
		mov dwSize, eax

		Invoke LocalAlloc, LMEM_FIXED or LMEM_ZEROINIT, dwSize
		mov esi, eax
		.if (!eax)
			invoke CloseHandle, ebx
			jmp error
		.endif
		Invoke ReadFile, ebx, esi, dwSize, addr dwRead, NULL
		mov eax,dwRead
		.if (eax != dwSize)
			invoke LocalFree, esi
			invoke CloseHandle, ebx
			jmp error
		.endif
		invoke CloseHandle, ebx
		mov eax, esi
		mov edx, dwSize
		@strace <"file read, buffer=", eax, " size=", edx>
exit:
		ret
error:
		xor eax,eax
		jmp exit

		align 4
LoadFile endp        

PlaySound proc uses ebx esi edi pImage:ptr

local	dwBuffSize:DWORD
local	pWavBuff:DWORD
local	pWavBuffEnd:DWORD
local	hWaveOut:DWORD
local	dwFlags1:dword
local	WavHdr1:WAVEHDR
local	WavFormat:WAVEFORMATEX
local	mmt:MMTIME

		@strace <"PlaySound, image=", pImage>
		mov esi, pImage
        
		.if ([esi].RIFFHDR.chkId != "FFIR")
			@strace <"no RIFF header found">
			jmp exit
		.endif
		.if ([esi].RIFFHDR.format != "EVAW")
			@strace <"not a WAVE format">
			jmp exit
		.endif
		add esi, sizeof RIFFHDR

		.if ([esi].WAVEFMT.subchkId != " tmf")
			@strace <"no fmt chunk found">
			jmp exit
		.endif
		mov edi, esi
		add esi, sizeof WAVEFMT

		.if ([esi].RIFFCHKHDR.subchkId != "atad")
			@strace <"no data chunk found">
			jmp exit
		.endif
		mov eax, [esi].RIFFCHKHDR.subchkSiz
		mov dwBuffSize, eax
		@strace <"PlaySound: sound data size=", eax>

		lea eax, [esi+sizeof RIFFCHKHDR]
		mov pWavBuff, eax

		mov eax, pWavBuff
		add eax, dwBuffSize
		mov pWavBuffEnd, eax

		lea ebx, WavFormat
		mov [ebx].WAVEFORMATEX.cbSize,sizeof WAVEFORMATEX	
		mov ax, [edi].WAVEFMT.wFormatTag
		mov [ebx].WAVEFORMATEX.wFormatTag, ax
		mov ax, [edi].WAVEFMT.nChannels
		mov [ebx].WAVEFORMATEX.nChannels,ax
		mov eax, [edi].WAVEFMT.nSamplesPerSec
		mov [ebx].WAVEFORMATEX.nSamplesPerSec, eax
		mov eax, [edi].WAVEFMT.nAvgBytesPerSec
		mov [ebx].WAVEFORMATEX.nAvgBytesPerSec, eax
		mov ax, [edi].WAVEFMT.nBlockAlign
		mov [ebx].WAVEFORMATEX.nBlockAlign, ax
		mov ax, [edi].WAVEFMT.wBitsPerSample
		mov [ebx].WAVEFORMATEX.wBitsPerSample, ax

		Invoke waveOutOpen, addr hWaveOut, WAVE_MAPPER, ebx, 0, NULL, CALLBACK_NULL
		.if (eax != MMSYSERR_NOERROR)
			@strace <"waveOutOpen() failed">
			jmp exit
		.endif

		.if (dwFlags & SND_LOOP)
			mov dwFlags1, WHDR_BEGINLOOP or WHDR_ENDLOOP
		.else
			mov dwFlags1, 0
		.endif

		lea ebx, WavHdr1
		mov ecx, dwFlags1
		mov [ebx].WAVEHDR.dwFlags, ecx
		.if (dwFlags & SND_LOOP)
			mov [ebx].WAVEHDR.dwLoops, -1
		.else
			mov [ebx].WAVEHDR.dwLoops, 0
		.endif
		mov eax, pWavBuff
		mov [ebx].WAVEHDR.lpData, eax
		mov eax, pWavBuffEnd
		sub eax, pWavBuff
		mov [ebx].WAVEHDR.dwBufferLength, eax
		invoke waveOutPrepareHeader, hWaveOut, ebx, sizeof WAVEHDR
		.if (eax == MMSYSERR_NOERROR)
			Invoke waveOutWrite, hWaveOut, ebx, sizeof WAVEHDR
			@strace <"waveOutWrite()=", eax>
			.if (eax == MMSYSERR_NOERROR)
				.while (g_bCancel == 0)
					invoke Sleep,0
					.break .if (WavHdr1.dwFlags & WHDR_DONE)
				.endw
			.endif
			lea ebx, WavHdr1
			invoke waveOutUnprepareHeader, hWaveOut, ebx, sizeof WAVEHDR
		.endif
		invoke waveOutClose, hWaveOut
		mov hWaveOut, 0
exit:
		.if (!(dwFlags & SND_MEMORY))
			invoke LocalFree, pImage
		.endif
		@strace <"PlaySound exit">
		ret
		align 4
PlaySound endp

sndPlaySoundA proc public uses ebx lpszSound:ptr byte, fuSound:dword

		invoke waveOutGetNumDevs
		and eax, eax
		jz exit
		mov eax, lpszSound
		.if (eax)
			mov ebx, fuSound
			mov dwFlags, ebx
			.if (ebx & SND_MEMORY)
			.else
				invoke LoadFile, eax
				and eax, eax
				jz exit
			.endif
			mov g_bCancel,0
			.if (ebx & SND_ASYNC)
				.if (hThread)
					invoke WaitForSingleObject, hThread, INFINITE
					invoke CloseHandle, hThread
				.endif
				push 0
				invoke CreateThread, 0, 0, PlaySound, eax, 0, esp
				mov hThread, eax
				pop eax
			.else
				invoke PlaySound, eax
			.endif
		.elseif (hThread)
			mov g_bCancel, 1
			invoke WaitForSingleObject, hThread, INFINITE
			xor eax, eax
			xchg eax, hThread
			invoke CloseHandle, eax
		.endif
exit:
		@strace <"sndPlaySoundA(", lpszSound, ", ", fuSound, ")=", eax>
		ret
		align 4

sndPlaySoundA endp

	end
